package com.example.myproject.redis.redission.service;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * redislock单价解决不了master 突然宕机的问题，会再master 选举slave的时候，有并发冲突问题
 * leaseTime 测试下这个释放是锁的释放时间，默认设置10分钟，还是30s
 *
 */
@Component
public class RedisLockHelper {
    private static final Logger logger = LoggerFactory.getLogger(RedisLockHelper.class);

    @Autowired
    private RedissionConfiguration redissionConfiguration;

    @Autowired
    private RedissonClient redissonClient;



    @Resource
    RedisOpsKeyClient keyClient;

    @Autowired
    RedisOpsHashClient redisOpsHashClient;

    @Autowired
    RedisOpsValueClient redisOpsValueClient;


    public static final String  SPLIT = "--item--";


    private  String getKey(String companyUuid,Integer assessType,String date){
        return "scoreRemind:"+StringUtil.getTrimString(companyUuid)+SPLIT+ SPLIT + StringUtil.getTrimString(assessType) +SPLIT + StringUtil.getTrimString(date);
    }

    public void setSendMsgFlag(String companyUuid,String empUuid,Integer assessType,String date){
        String key = getKey(companyUuid,assessType,date);
        redisOpsHashClient.put(key,empUuid,Boolean.TRUE);
        keyClient.expire(key, 24 * 3600);
    }

    private String getCallTotalKey(String companyUuid,String uniqueId){
        String key = companyUuid+":uniqueId:" + uniqueId;
        return key;
    }
    public void setUniqueId(String companyUuid,String uniqueId){
        if(StringUtil.isBlank(uniqueId)){
            return;
        }
        String key = getCallTotalKey(companyUuid,uniqueId);
        redisOpsValueClient.set(key,Boolean.TRUE);
        keyClient.expire(key, 2 * 24 * 3600);
    }

    public Boolean existUniqueId(String companyUuid,String uniqueId){
        String key = getCallTotalKey(companyUuid,uniqueId);
        Object value = redisOpsValueClient.get(key);
        return  value!=null && Boolean.TRUE.equals(value);
    }


    /**
     *
     * @param companyUuid
     * @param empUuid
     * @param assessType
     * @param date
     * @return
     */
    public Boolean isSendMsgForUserOneDay(String companyUuid,String empUuid,Integer assessType,String date){
        try{
            String key = getKey(companyUuid,assessType,date);
            Object value = redisOpsHashClient.get(key,empUuid);
            return  value!=null && Boolean.TRUE.equals(value);
        }catch (Exception e){
            logger.error("isSendMsgForUserOneDayError",e);
            return  false;
        }
    }

    //@SuppressWarnings("squid:S2222")
    public RLock tryLock(String empUuid, String traceUuid) {
        boolean flag;
        RLock rLock = redissonClient.getLock(getLockName(empUuid, traceUuid));
        try {
            flag = rLock.tryLock(redissionConfiguration.getWaitTimeOfInitEs(), redissionConfiguration.getReleaseTimeOfInitEs(), TimeUnit.MINUTES);
            if (!flag) {
                logger.warn("The getLock fail!!! empUuid-:{} traceUuid:{}", empUuid, traceUuid);
                //throw new BusinessException();
            }
        } catch (InterruptedException e) {
            logger.error("The getLock error!!! empUuid-:{}  traceUuid:{}", empUuid, traceUuid);
            //throw new BusinessException(CommonResponseCode.RC_EXCEPTION_ERROR.getResponseCode(), CommonResponseCode.RC_EXCEPTION_ERROR.getResponseMessage());
        }
        return rLock;
    }

    //@SuppressWarnings("squid:S2222")
    public RLock tryLock(String dataUuid) {
        boolean flag;
        RLock rLock = redissonClient.getLock(getLockName(dataUuid));
        try {
            flag = rLock.tryLock(redissionConfiguration.getWaitTimeOfInitEs(), redissionConfiguration.getReleaseTimeOfInitEs(), TimeUnit.MINUTES);
            if (!flag) {
                logger.warn("The getLock fail!!! dataUuid-:{}", dataUuid);
                //throw new BusinessException();
            }
        } catch (InterruptedException e) {
            logger.error("The getLock error!!! dataUuid-:{} ", dataUuid);
            //throw new BusinessException(CommonResponseCode.RC_EXCEPTION_ERROR.getResponseCode(), CommonResponseCode.RC_EXCEPTION_ERROR.getResponseMessage());
        }
        return rLock;
    }

    /**
     *
     * case1:A一致锁着，不释放锁了，B会一直等待把
     * @param dataUuid
     * @return
     */
    public RLock tryLockInTime(String dataUuid,int waitEsInSeconds,int releaseInSeconds) {
        boolean flag;
        RLock rLock = redissonClient.getLock(getLockName(dataUuid));
        try {
            flag = rLock.tryLock(waitEsInSeconds,releaseInSeconds, TimeUnit.SECONDS);
            if (!flag) {
                logger.warn("The getLock fail!!! dataUuid:{}", dataUuid);
                //throw new BusinessException();
            }
            logger.info("theadname:"+Thread.currentThread().getName()+",getlockdata,flag:{}",flag);
        } catch (InterruptedException e) {
            logger.error("The getLock error!!! dataUuid-:{} ", dataUuid);
            //throw new BusinessException(CommonResponseCode.RC_EXCEPTION_ERROR.getResponseCode(), CommonResponseCode.RC_EXCEPTION_ERROR.getResponseMessage());
        }
        return rLock;
    }

    public void forceUnlock(String dataUuid) {
        RLock rLock = redissonClient.getLock(getLockName(dataUuid));
        if (rLock != null && rLock.isLocked()) {
            logger.info("The dataUuid:{} forceUnlock success!!!",dataUuid);
            rLock.forceUnlock();
        }else{
            logger.info("The dataUuid:rockNotlocked",dataUuid);
        }
    }


    public RLock getLockByDataUuid(String dataUuid) {
        RLock rLock = redissonClient.getLock(getLockName(dataUuid));
        return  rLock;

    }

    public void forceUnLock(String empUuid, String traceUuid) {
        RLock rLock = redissonClient.getLock(getLockName(empUuid, traceUuid));
        if (rLock != null && rLock.isLocked()) {
            logger.info("The getLock success!!!");
            rLock.forceUnlock();
        }
    }


    public String getLockName(String empUuid, String traceUuid) {

        return "score_lock_key_"  + "_" + empUuid + "_" + traceUuid;
    }

    public String getLockName(String dataUuid) {
        return "score_lock_key_"+dataUuid;
    }




}